#!/usr/bin/env python3
"""
XML语法高亮器
支持XML文件的高亮显示
"""

from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor

class XMLHighlighter(QSyntaxHighlighter):
    """XML语法高亮器"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.highlighting_rules = []
        
        # 标签格式
        tag_format = QTextCharFormat()
        tag_format.setForeground(QColor(255, 128, 0))  # 橙色
        tag_format.setFontWeight(75)
        
        # 属性名格式
        attribute_name_format = QTextCharFormat()
        attribute_name_format.setForeground(QColor(0, 0, 255))  # 蓝色
        
        # 属性值格式
        attribute_value_format = QTextCharFormat()
        attribute_value_format.setForeground(QColor(163, 21, 21))  # 深红色
        
        # 注释格式
        comment_format = QTextCharFormat()
        comment_format.setForeground(QColor(0, 128, 0))  # 绿色
        comment_format.setFontItalic(True)
        
        # CDATA格式
        cdata_format = QTextCharFormat()
        cdata_format.setForeground(QColor(128, 0, 128))  # 紫色
        
        # 处理指令格式
        processing_instruction_format = QTextCharFormat()
        processing_instruction_format.setForeground(QColor(128, 128, 0))  # 橄榄色
        
        # 添加规则
        
        # XML声明
        rule = (QRegExp(r'<\?xml[^>]*\?>'), tag_format)
        self.highlighting_rules.append(rule)
        
        # 开始标签
        rule = (QRegExp(r'<\w+'), tag_format)
        self.highlighting_rules.append(rule)
        
        # 结束标签
        rule = (QRegExp(r'</\w+'), tag_format)
        self.highlighting_rules.append(rule)
        
        # 自闭合标签
        rule = (QRegExp(r'/>'), tag_format)
        self.highlighting_rules.append(rule)
        
        # 标签闭合
        rule = (QRegExp(r'>'), tag_format)
        self.highlighting_rules.append(rule)
        
        # 属性名
        rule = (QRegExp(r'\b\w+\s*='), attribute_name_format)
        self.highlighting_rules.append(rule)
        
        # 属性值
        rule = (QRegExp(r'"[^"]*"'), attribute_value_format)
        self.highlighting_rules.append(rule)
        rule = (QRegExp(r"'[^']*'"), attribute_value_format)
        self.highlighting_rules.append(rule)
        
        # 注释
        rule = (QRegExp(r'<!--[^-]*(?:-[^-]+)*-->'), comment_format)
        self.highlighting_rules.append(rule)
        
        # CDATA
        rule = (QRegExp(r'<!\[CDATA\[.*?\]\]>'), cdata_format)
        self.highlighting_rules.append(rule)
        
        # 处理指令
        rule = (QRegExp(r'<\?[^>]*\?>'), processing_instruction_format)
        self.highlighting_rules.append(rule)
        
        # 多行注释
        self.comment_start_expression = QRegExp(r'<!--')
        self.comment_end_expression = QRegExp(r'-->')
        self.comment_format = comment_format
        
        # CDATA块
        self.cdata_start_expression = QRegExp(r'<!\[CDATA\[')
        self.cdata_end_expression = QRegExp(r'\]\]>')
        self.cdata_format = cdata_format
    
    def highlightBlock(self, text):
        """高亮文本块"""
        # 应用单行规则
        for pattern, format in self.highlighting_rules:
            expression = QRegExp(pattern)
            index = expression.indexIn(text)
            while index >= 0:
                length = expression.matchedLength()
                self.setFormat(index, length, format)
                index = expression.indexIn(text, index + length)
        
        # 处理多行注释
        self.setCurrentBlockState(0)
        
        start_index = 0
        if self.previousBlockState() != 1:
            start_index = self.comment_start_expression.indexIn(text)
        
        while start_index >= 0:
            end_index = self.comment_end_expression.indexIn(text, start_index)
            if end_index == -1:
                self.setCurrentBlockState(1)
                comment_length = len(text) - start_index
                self.setFormat(start_index, comment_length, self.comment_format)
                break
            else:
                comment_length = end_index - start_index + self.comment_end_expression.matchedLength()
                self.setFormat(start_index, comment_length, self.comment_format)
                start_index = self.comment_start_expression.indexIn(text, start_index + comment_length)
        
        # 处理CDATA块
        cdata_start_index = 0
        if self.previousBlockState() != 2:
            cdata_start_index = self.cdata_start_expression.indexIn(text)
        
        while cdata_start_index >= 0:
            cdata_end_index = self.cdata_end_expression.indexIn(text, cdata_start_index)
            if cdata_end_index == -1:
                self.setCurrentBlockState(2)
                cdata_length = len(text) - cdata_start_index
                self.setFormat(cdata_start_index, cdata_length, self.cdata_format)
                break
            else:
                cdata_length = cdata_end_index - cdata_start_index + self.cdata_end_expression.matchedLength()
                self.setFormat(cdata_start_index, cdata_length, self.cdata_format)
                cdata_start_index = self.cdata_start_expression.indexIn(text, cdata_start_index + cdata_length)